/*
 * Programa: IpCalc - Calculadora de IP's Classe C 
 * Descri��o: O programa IpCalc c�lcula a tabela de subnet de dimens�o fixa para um dado IP da classe.
 *
 * Autor:  David Ervideira
 * 
 * Vers�o: 1.1.1
 * 		   1.1 > 1.1.1 : Corrigido: Endere�o de Broadcast trocada com o Gateway
 * 		   1.0 > 1.1 : String de sa�da formatada correctamente
 * 
 * Data:   1.1.1 > 08-12-2012
 * 		   1.1 >   08-12-2012
 *         1.0 >   30-09-2012
 *         
 * �mbito: Projecto da UFCD-5091 do curso GRSI da turma GRSIPL0912A  da ATEC
 * 
 */

/* Alteração ao comentario só para testar */

/* Bibliotecas */
import java.awt.*;
import java.awt.event.*;

public class IpCalc extends Frame implements ActionListener, ItemListener  {

	/* Dados */
	
	private static final long serialVersionUID = 1L;
	
	Panel centro, sul, norte;
	Label lb_oct1, lb_oct2, lb_oct3, lb_oct4;
	TextField tf_oct1, tf_oct2, tf_oct3, tf_oct4;
	TextArea ta_1;
	Button bt_calc, bt_apagar, bt_sair;
	Choice ch_mask;
	MenuBar menu_bar;
	Menu menu;
	MenuItem item_op1, item_op2, item_op3;
	
	String str_msg_init = "\n					Calculadora IPv4 Classe C";
	String str_msg_erro_1 = "Erro 1: O n�mero introduzido n�o est� dentro do intervalo v�lido para IP's!";
	String str_msg_erro_2 = "Erro 2: O IP introduzido parece n�o ser da classe C!";
	String str_msg_erro_3 = "Erro 3: Devem ser introduzidos n�meros inteiros em todos os octetos!";
	
	static int bits_seg = 0;
	static int oct1 = 0, oct2 = 0, oct3 = 0, oct4 = 0;
	
	
	/* Construtor */
	public IpCalc(){
		 /* Titulo */
		super("IpCalc - Calculadora IPv4 Classe C (v1.2)");
		
		
		/* Menu */
		menu_bar = new MenuBar();
		menu = new Menu("Op��es");
		item_op1 = new MenuItem("Calcular");
		item_op1.addActionListener(this);
		menu.add(item_op1);
		item_op2 = new MenuItem("Apagar");
		item_op2.addActionListener(this);
		menu.add(item_op2);
		menu.addSeparator();
		item_op3 = new MenuItem("Sair");
		item_op3.addActionListener(this);
		menu.add(item_op3);
		
		menu_bar.add(menu);
		setMenuBar(menu_bar);
		
		/* Painel Norte */
		norte = new Panel( new FlowLayout(FlowLayout.CENTER) );
		
		lb_oct1 = new Label("1� Octeto", Label.CENTER);
		norte.add(lb_oct1);
		tf_oct1 = new TextField(5);
		norte.add(tf_oct1);
		
		lb_oct2 = new Label("2� Octeto", Label.CENTER);
		norte.add(lb_oct2);
		tf_oct2 = new TextField(5);
		norte.add(tf_oct2);
		
		lb_oct3 = new Label("3� Octeto", Label.CENTER);
		norte.add(lb_oct3);
		tf_oct3 = new TextField(5);
		norte.add(tf_oct3);
		
		lb_oct4 = new Label("4� Octeto", Label.CENTER);
		norte.add(lb_oct4);
		tf_oct4 = new TextField(5);
		norte.add(tf_oct4);
		
		add(norte, BorderLayout.NORTH);
		
		/* Painel Centro */
		centro = new Panel(new GridLayout(1,1) );
		
		ta_1 = new TextArea(str_msg_init);
		//ta_1.setEditable(false);
		centro.add(ta_1);
		
		add(centro, BorderLayout.CENTER);
		
		/* Painel Sul */
		sul = new Panel(new GridLayout(1,4));
		
		bt_calc = new Button("Calcular");
		bt_calc.addActionListener(this);
		sul.add(bt_calc);
		bt_apagar = new Button("Apagar");
		bt_apagar.addActionListener(this);
		sul.add(bt_apagar);
		bt_sair = new Button("Sair");
		bt_sair.addActionListener(this);
		sul.add(bt_sair);
		
		ch_mask = new Choice();
		ch_mask.add("Retirar 0 bits");
		ch_mask.add("Retirar 1 bit ");
		ch_mask.add("Retirar 2 bits");
		ch_mask.add("Retirar 3 bits");
		ch_mask.add("Retirar 4 bits");
		ch_mask.add("Retirar 5 bits");
		ch_mask.add("Retirar 6 bits");
		
		ch_mask.addItemListener(this);
		sul.add(ch_mask);
		
		add(sul, BorderLayout.SOUTH);
		
		tf_oct1.setText("192");
		tf_oct2.setText("168");
		tf_oct3.setText("0");
		tf_oct4.setText("0");
		
		setSize(640, 480);
		setVisible(true);		
	}
	
	/* M�todos */
	public void actionPerformed(ActionEvent e){
		
		/* Sair */
		if( (e.getSource() == bt_sair) || (e.getSource() == item_op3)  ){
			System.exit(0);
		}
		/* Apagar */
		if( e.getSource() == bt_apagar || (e.getSource() == item_op2)  ){
			tf_oct1.setText("");
			tf_oct2.setText("");
			tf_oct3.setText("");
			tf_oct4.setText("");
			ta_1.setText(str_msg_init);
		}
		/* Calcular */
		if( e.getSource() == bt_calc || (e.getSource() == item_op1)  ){
			
			try{
				
				oct1 = Integer.parseInt( tf_oct1.getText() ); // Captura do primeiro octeto
				oct2 = Integer.parseInt( tf_oct2.getText() ); // Captura do segundo octeto
				oct3 = Integer.parseInt( tf_oct3.getText() ); // Captura do terceiro octeto
				oct4 = Integer.parseInt( tf_oct4.getText() ); // Captura do quarto octeto
				
				/* Verifica��es de erro */
				if( (oct1>255 || oct1<0) || (oct2>255 || oct2<0) || (oct3>255 || oct3<0) || (oct4>255 || oct4<0) ) //Verifica��o se est� dentro da range de ip
					ta_1.setText(str_msg_erro_1);
				else if( oct1<192 || oct1>223 ) //Verifica��o se o ip � classe C
					ta_1.setText(str_msg_erro_2);
				else
					ta_1.setText( IpSeg(bits_seg) ); //Caso n�o haja erro, prosseguir com a execu��o e colocar na TextArea a string de saida
				
			}catch(NumberFormatException nfe) {  //Verifica��o se foi introduzido texto
				ta_1.setText(str_msg_erro_3);
			};
			}
		}
		
		
		
	
	
	public void itemStateChanged(ItemEvent e){
		/* Afecta��o da variavel que contem os bits retirados atraves do objecto Choice */
		int index = 0;
		if( e.getSource() == ch_mask ){
			index = ch_mask.getSelectedIndex();
			switch(index){
			case 0: bits_seg = 0; break;
			case 1: bits_seg = 1; break;
			case 2: bits_seg = 2; break;
			case 3: bits_seg = 3; break;
			case 4: bits_seg = 4; break;
			case 5: bits_seg = 5; break;
			case 6: bits_seg = 6; break;
			}
		}
		
	}
	
	public static String IpSeg(int bits_seg){
		
	    /*
	     * 
	     * Descri��o:       M�todo que c�lcula e compoe a string de saida.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com os bits a retirar e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   (comentado ao longo do m�todo) 
	     *                  Este M�todo faz uso de v�rios m�todos auxiliares
	     * 
	     */
		
		String res="";
		int i = 0, rede = 0, dim = 0;
		
		/* Composi��o das informa��es iniciais */
		res = "\tC�lculo do IP inserido = "+oct1+"."+oct2+"."+oct3+"."+oct4+"\n\n\n";
		res += "\tIP Classe: C\n\tComposi��o: 110NNNNN.NNNNNNNN.NNNNNNNN.HHHHHHHH\n\n";
		res += "\tTr�s Octetos [NET_ID]\tUm Octeto [HOST_ID]\n\tRFC(1918)\n\n";
		
		res += "\tCom segmenta��o\n";
		res += "\t\tHost\tHost\tHost\tHost\n";
		res += "\tGrupo\tRede\tInicio\tFim\tBroad\tGateway\t\tDim\tCIDR\tM�scara\n"; //titulos das colunas
		
		dim = 256 / powerInt(2, bits_seg); //calculo da dimensao das redes
		
		/* ciclo for para produzir a tabela de segumenta��o */
		for(i=0;i<powerInt(2, bits_seg);i++){		
			
			res += "\t"+i+"\t"+rede+"\t"+(rede+1)+"\t"+(rede+powerInt(2, 8-bits_seg)-2)+"\t"+(rede+powerInt(2, 8-bits_seg)-1)+"\t"+(rede+powerInt(2, 8-bits_seg)-2);
			res += "\t\t"+dim;
			res += "\t" + MaskCIDR(bits_seg);
			res += "\t"+MaskIP(dim);
			res += "\t\n";
			
			rede += powerInt(2, 8-bits_seg);
		}
		res += "\n";
		
		/* Composi��o das informa��es finais */
		res += "\t"+NmrCartoExt(i+1)+" Conjuntos\t\t"+dim+" Endere�os em cada conjunto"+"\n\n";
		res += "\tRedes = "+(i)+"\t\t\tEndere�os = "+dim+"\n";
		res += "\tUsaveis = "+(i-2)+"\t\t\tUsaveis = "+(dim-2)+"\n\n";
		res += "\tComposi��o = "+composicaoBin(bits_seg)+"\n\n";
		res += "\tTr�s Octetos [NET_ID]\tUmOcteto "+composicaoOct(bits_seg);
		
		return res;
	}
	
	static public String MaskIP(int dim){
		
	    /*
	     * 
	     * Descri��o:       M�todo que c�lcula a mascara de rede em IP.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com a dimensao e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   Uma vez que se trata Ips apenas da classe C os tres primeiros octetos 
	     *                  sao sempre 255.
	     *                  O quarto octeto � calculado substraindo a dimensao a 256. 
	     * 
	     */
		
		String res="255.255.255.";

		res += Integer.toString( 256-dim );
		
		return res;
		
	}
	
	static public String MaskCIDR(int bits){
		
	    /*
	     * 
	     * Descri��o:       M�todo que c�lcula a mascara de rede em CIDR.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com os bits retirados e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   Uma vez que se trata Ips apenas da classe C os tres primeiros octetos 
	     *                  quando n�o sao retirados bits a mascara � sempre /24.
	     *                  Quando sao retirados bits a mascara � calculada adicionando os bits
	     *                  retirados a 24. 
	     * 
	     */
		
		String res="";
		
		res = "/" + Integer.toString( 24+bits );
		
		return res;
	}
	
	static public int powerInt(int b, int e){
		
	    /*
	     * 
	     * Descri��o:       M�todo que calcula uma potencia.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com os bits retirados e retorna um 
	     * 					 inteiro com o resultado
	     * 
	     * Funcionamento:   Calculo de uma potencia. Multiplica a base por ela pr�pria o tantas
	     *                  vezes quanto o numero no expoente.
	     * 
	     */
		
		int i=0, res=1;
		
		for(i=1;i<=e;i++)
			res = b * res;
		return res;
	}
	
	static public String NmrCartoExt(int nmr){
		
	    /*
	     * 
	     * Descri��o:       M�todo que converte um numero numa string por extenso.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com o numero e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   Um switch que associa o numero ao texto em extenso correspondente
	     * 
	     */
		
		String res="";
		
		switch (nmr) {
		
		case 1: res = "Um"; break;
		case 2: res = "Dois"; break;
		case 4: res = "Quatro"; break;
		case 8: res = "Oito"; break;
		case 16: res = "Dezesseis "; break;
		case 32: res = "Trinta e dois"; break;
		case 64: res = "Sessenta e quatro"; break;
		
		}
		
		return res;
	}
	
	static public String composicaoBin(int bits){
		
	    /*
	     * 
	     * Descri��o:       M�todo que c�lcula a composi�ao por binario.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com os bits retirados e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   Uma vez que se trata Ips apenas da classe C os tres primeiros octetos 
	     *                  s�o sempre iguais.
	     *                  O quarto octeto � preenchido de acordo com os bits retirados.
	     * 
	     */
		
		String res = "NNNNNNNN.NNNNNNNN.NNNNNNNN.";
		int i=0;
		
		for(i=1;i<=8;i++){
			
			if( i<=bits )
				res += "S"; //se for menos que os bits retirados, adiciona S 
			else
				res +="H"; //caso contrario preenche as posi�oes restantes com 'H'
			
		}
		
		return res;
	}
	
	static public String composicaoOct(int bits){
		
	    /*
	     * 
	     * Descri��o:       M�todo que c�lcula a composi�ao por octetos.
	     * 
	     * Inputs e Outputs: O M�todo recebe um n�mero inteiro com os bits retirados e retorna uma 
	     * 					 string om o resultado de sa�da
	     * 
	     * Funcionamento:   Uma vez que se trata Ips apenas da classe C os tres primeiros octetos 
	     *                  s�o sempre iguais.
	     *                  O quarto octeto � preenchido de acordo com os bits retirados.
	     * 
	     */
		
		String res = "";
		
		res = "[ SUBNET ("+(bits)+" Bits) -- HOST_ID ("+(8-bits)+" Bits) ]";
		
		return res;
	}
	
	public static void main(String[] args) {
		 
		 IpCalc app = new IpCalc();
		 
		 app.addWindowListener(new WindowAdapter()           //para o X da janela funcionar
	   		{
	   			public void windowClosing(WindowEvent e)
	   			{
	   				System.exit(0);
	   			}
		});
		 
	 }
}
